package cc.hanzs.json;

/**
 *
 * @author 韩占山
 */
public final class JSONObject extends java.util.TreeMap<String, Object> implements Cloneable, java.io.Serializable {

    private JSONObject() {
    }

    private String path_s = null;
    protected Object parent = null;
    private static final JSONObject i_JSON = new JSONObject();

    protected void set(final JSONTokener x) throws JSONException {
        this.clear();
        char c;
        String key;
        Object value;

        if (x.nextClean() != '{') {
            throw new JSONException("JSON文本必需以'{'开始！");
        }
        for (;;) {
            c = x.nextClean();
            switch (c) {
                case 0:
                    throw new JSONException("JSON文本必需以'}'结束！");
                case '}':
                    return;
                default:
                    x.back();
                    key = x.nextValue(null).toString();
            }

            /*
             * The key is followed by ':'. We will also tolerate '=' or '=>'.
             */
            c = x.nextClean();
            if (c == '=') {
                if (x.next() != '>') {
                    x.back();
                }
            } else if (c != ':') {
                throw new JSONException("Expected a ':' after a key");
            }
            value = x.nextValue(this);
            if (value != null) {
                super.put(key, value);
            }

            /*
             * Pairs are separated by ','. We will also tolerate ';'.
             */
            switch (x.nextClean()) {
                case ';':
                case ',':
                    if (x.nextClean() == '}') {
                        return;
                    }
                    x.back();
                    break;
                case '}':
                    return;
                default:
                    throw new JSONException("Expected a ',' or '}'");
            }
        }
    }

    protected void setPath(Object root) {
        java.util.Iterator keys;
        Object value;
        String key;

        keys = keys();

        while (keys.hasNext()) {
            key = (String) keys.next();
            value = super.get(key);
            if (value instanceof JSONPath) {
                ((JSONPath) value).root = root;
                ((JSONPath) value).i当前 = this;
            } else if (value instanceof JSONObject) {
                ((cc.hanzs.json.JSONObject) value).setPath(root);
            } else if (value instanceof JSONArray) {
                ((cc.hanzs.json.JSONArray) value).setPath(root);
            }
        }
    }

    /**
     * @param ci_s 待解析文本
     * @return 解析生成的org.hzs.JSONObject
     */
    public JSONObject set(final String ci_s) throws JSONException {
        if (ci_s == null) {
            return null;
        }
        set(JSONTokener.d副本(ci_s));
        setPath(this);
        return this;
    }

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    protected static boolean testValidity(final Object value) {
        if (value == null) {
            return false;
        }
        if (value instanceof Double) {
            if (((Double) value).isInfinite() || ((Double) value).isNaN()) {
//                ci_error.g添加错误信息("JSON不允许非有限数");
//                throw ci_error;
                return false;
            }
        } else if (value instanceof Float) {
            if (((Float) value).isInfinite() || ((Float) value).isNaN()) {
//                ci_error.g添加错误信息("JSON不允许非有限数");
//                throw ci_error;
                return false;
            }
        }
        return true;
    }

    /**
     * @param key 待加入的键，为空时不加入
     * @param value 待加入的值，为空时不加入
     * @return 加入的值
     */
    @Override
    public Object put(final String key, final Object value) {
        if (key == null) {
            return null;
        }

        if (value == null) {
            super.remove(key);
            return null;
        }

        if (value instanceof Double || value instanceof Float) {
            if (testValidity(value)) {
                super.put(key, value);
                return value;
            } else {
                return null;
            }
        }

        super.put(key, value);
        return value;
    }

    /**
     * @param key 待加入的键，为空时不加入
     * @param value 待加入的值，为空时不加入
     * @return 加入的值
     */
    public Object put(final String key, final java.util.Date value) {
        if (key == null) {
            return null;
        }
        if (value == null) {
            super.remove(key);
            return null;
        }
        super.put(key, value.getTime());
        return value;
    }

    /**
     * @param key 待加入的键，为空时不加入
     * @param value 待加入的值，为空时不加入
     * @return 加入的值
     */
    public Object put(final String key, final java.util.Calendar value) {
        if (key == null) {
            return null;
        }
        if (value == null) {
            super.remove(key);
            return null;
        }
        super.put(key, value.getTimeInMillis());
        return value;
    }
    ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    /**
     * @since
     */
    private static String quote(final String string) {
        if (string == null || string.length() == 0) {
            return "\"\"";
        }

        char b;
        char c = 0;
        int i;
        int len = string.length();
        StringBuilder sb = new StringBuilder(len + 4);
        String t;

        sb.append('"');
        for (i = 0; i < len; i += 1) {
            b = c;
            c = string.charAt(i);
            switch (c) {
                case '\\':
                case '"':
                    sb.append('\\');
                    sb.append(c);
                    break;
                case '/':
                    if (b == '<') {
                        sb.append('\\');
                    }
                    sb.append(c);
                    break;
                case '\b':
                    sb.append("\\b");
                    break;
                case '\t':
                    sb.append("\\t");
                    break;
                case '\n':
                    sb.append("\\n");
                    break;
                case '\f':
                    sb.append("\\f");
                    break;
                case '\r':
                    sb.append("\\r");
                    break;
                default:
                    if (c < ' ') {
                        t = "000" + Integer.toHexString(c);
                        sb.append("\\u").append(t.substring(t.length() - 4));
                    } else {
                        sb.append(c);
                    }
            }
        }
        sb.append('"');
        return sb.toString();
    }

    /**
     * @param key 文本型
     * @return 返回任意类型的值；若key不存在，则返回空值。
     */
    @Override
    public Object get(final Object key) {
        if (key == null) {
            return null;
        }
        if (super.containsKey(key)) {
            return super.get(key);
        } else {
            return null;
        }
    }

    /**
     * @param key 文本型
     * @return 返回字节型的值；若key不存在，则返回空值。
     */
    public Byte getByte(final Object key) {
        Object o = get(key);
        if (o == null) {
            return null;
        }
        if (o instanceof Number) {
            return ((Number) o).byteValue();
        }
        return Byte.valueOf(o.toString());
    }

    /**
     * @param key 文本型
     * @return 返回逻辑型的值；若key不存在，则返回空值。
     */
    public Boolean getBoolean(final Object key) {
        Object o = get(key);
        if (o == null) {
            return null;
        }
        if (o.equals(Boolean.FALSE)
                || (o instanceof String && ((String) o).equalsIgnoreCase("false"))
                || (o instanceof Number && !((Number) o).equals(0))) {
            return false;
        } else if (o.equals(Boolean.TRUE)
                || (o instanceof String && ((String) o).equalsIgnoreCase("true"))) {
            return true;
        }
        return null;
    }

    /**
     * @param key 文本型
     * @return 返回双精度型的值；若key不存在，则返回空值；若出错，返回空值。
     */
    public Double getDouble(final Object key) {
        Object o = get(key);
        try {
            if (o == null) {
                return null;
            }
            if (o instanceof Number) {
                return ((Number) o).doubleValue();
            }
            return Double.valueOf(o.toString());
        } catch (NumberFormatException e) {
            return null;
        }
    }

    /**
     * @param key 文本型
     * @return 返回单精度型的值；若key不存在，则返回空值；若出错，返回空值。
     */
    public Float getFloat(final Object key) {
        Object o = get(key);
        try {
            if (o == null) {
                return null;
            }
            if (o instanceof Number) {
                return ((Number) o).floatValue();
            }
            return Float.valueOf(o.toString());
        } catch (NumberFormatException e) {
            return null;
        }
    }

    /**
     * @param key 文本型
     * @return 返回日期时间型的值；若key不存在，则返回空值。
     */
    public java.util.Date getDate(final Object key) {
        Object o;

        o = get(key);
        if (o == null) {
            return null;
        }
        if (o instanceof java.util.Date) {
            return (java.util.Date) o;
        }
        if (o instanceof Number) {
            return new java.util.Date(((Number) o).longValue());
        }
        if (o instanceof String) {
            return new java.util.Date((String) o);
        }
        return null;
    }

    /**
     * @param key 文本型
     * @return 返回日期时间型的值；若key不存在，则返回空值。
     */
    public java.util.Calendar getCalendar(final Object key) {
        Object o;
        java.util.Calendar value;

        o = get(key);
        if (o == null) {
            return null;
        }
        if (o instanceof java.util.Calendar) {
            return (java.util.Calendar) o;
        }
        if (o instanceof java.util.Date) {
            value = java.util.Calendar.getInstance();
            value.setTimeInMillis(((java.util.Date) o).getTime());
            return value;
        }
        if (o instanceof Number) {
            value = java.util.Calendar.getInstance();
            value.setTimeInMillis(((Number) o).longValue());
            return value;
        }
        if (o instanceof String) {
            value = java.util.Calendar.getInstance();
            value.setTimeInMillis((new java.util.Date((String) o)).getTime());
            return value;
        }
        return null;
    }

    /**
     * @param key 文本型
     * @return 返回任意大浮点型的值；若key不存在，则返回空值；若出错，返回空值。
     */
    public java.math.BigDecimal getBigDecimal(final Object key) {
        Object o;
        try {
            o = get(key);
            if (o == null) {
                return null;
            }
            if (o instanceof java.math.BigDecimal) {
                return (java.math.BigDecimal) o;
            } else if (o instanceof Number) {
                return new java.math.BigDecimal(o.toString());
            } else if (o instanceof String) {
                if (o.equals("")) {
                    return java.math.BigDecimal.ZERO;
                } else {
                    return new java.math.BigDecimal((String) o);
                }
            } else {
                return null;
            }
        } catch (Exception e) {
            return null;
        } finally {
        }
    }

    /**
     * @param key 文本型
     * @return 返回任意大整型的值；若key不存在，则返回空值；若出错，返回空值。
     */
    public java.math.BigInteger getBigInteger(final Object key) {
        Object o;
        try {
            o = get(key);
            if (o == null) {
                return null;
            }
            if (o instanceof java.math.BigInteger) {
                return (java.math.BigInteger) o;
            } else if (o instanceof Number) {
                return new java.math.BigInteger(o.toString());
            } else if (o instanceof String) {
                if (o.equals("")) {
                    return java.math.BigInteger.ZERO;
                } else {
                    return new java.math.BigInteger((String) o);
                }
            } else {
                return null;
            }
        } catch (Exception e) {
            return null;
        } finally {
        }
    }

    /**
     * @param key 文本型
     * @return 返回整型的值；若key不存在，则返回空值。
     */
    public Integer getInt(final Object key) {
        Object o = get(key);
        if (o == null) {
            return null;
        }
        if (o instanceof Number) {
            return ((Number) o).intValue();
        }
        return Integer.valueOf(o.toString());
    }

    /**
     * @param key 文本型
     * @return 返回JSONArray型的值；若key不存在，则返回空值。
     */
    public JSONArray getJSONArray(final Object key) {
        Object o = get(key);
        if (o == null) {
            return null;
        }
        if (o instanceof JSONArray) {
            return (JSONArray) o;
        }
        return null;
    }

    /**
     * @param key 文本型
     * @return 返回JSONObject型的值；若key不存在，则返回空值。
     */
    public JSONObject getJSONObject(final Object key) {
        Object o = get(key);
        if (o == null) {
            return null;
        }
        if (o instanceof JSONObject) {
            return (JSONObject) o;
        }
        return null;
    }

    /**
     * @param key 文本型
     * @return 返回长整型的值；若key不存在，则返回空值。
     */
    public Long getLong(final Object key) {
        Object o = get(key);
        if (o == null) {
            return null;
        }
        if (o instanceof Number) {
            return ((Number) o).longValue();
        }
        return Long.valueOf(o.toString());
    }

    /**
     * @param key 文本型
     * @return 返回短整型的值；若key不存在，则返回空值。
     */
    public Short getShort(final Object key) {
        Object o = get(key);
        if (o == null) {
            return null;
        }
        if (o instanceof Short) {
            return ((Number) o).shortValue();
        }
        return Short.valueOf(o.toString());
    }

    /**
     * @param key 文本型
     * @return 返回文本型的值；若key不存在，则返回空值。
     */
    public String getString(final Object key) {
        Object o = get(key);
        if (o == null) {
            return null;
        }
        return o.toString();
    }

    /**
     * @param key 文本型
     * @return 返回JSONPath型的值；若key不存在，则返回空值。
     */
    public JSONPath getPath(final Object key) {
        Object o = get(key);
        if (o == null) {
            return null;
        }
        return (JSONPath) o;
    }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    /**
     * @return 返回key值集合
     */
    public java.util.Iterator keys() {
        return super.keySet().iterator();
    }

    private static String numberToString(final Number n) {
        if (n == null) {
            return null;
        }
        if (testValidity(n)) {

// Shave off trailing zeros and decimal point, if possible.
            String s = n.toString();
            if (s.indexOf('.') > 0 && s.indexOf('e') < 0 && s.indexOf('E') < 0) {
                while (s.endsWith("0")) {
                    s = s.substring(0, s.length() - 1);
                }
                if (s.endsWith(".")) {
                    s = s.substring(0, s.length() - 1);
                }
            }
            return s;
        } else {
            return null;
        }
    }

    /*
     * 将JSONObject的value转换为文本
     * @param value 任意类型，待转换成文本的值
     * @param cipath_s 序列化的路径
     * @return value生成的文本
     */
    protected static String valueToString(final Object value, final String cipath_s) {
        if (value == null) {
            return "null";
        }
        if (value instanceof java.math.BigDecimal) {
            return ((java.math.BigDecimal) value).toPlainString();
        }
        if (value instanceof java.util.Date) {
            return Long.toString(((java.util.Date) value).getTime());
        }
        if (value instanceof java.util.Calendar) {
            return Long.toString(((java.util.Calendar) value).getTimeInMillis());
        }
        if (value instanceof Number) {
            return numberToString((Number) value);
        }
        if (value instanceof String) {
            return quote(value.toString());
        }
        if (value instanceof cc.hanzs.json.JSONObject) {
            return ((cc.hanzs.json.JSONObject) value).toString(cipath_s);
        }
        if (value instanceof cc.hanzs.json.JSONArray) {
            return ((cc.hanzs.json.JSONArray) value).toString(cipath_s);
        }
        return value.toString();
    }

    /**
     *
     * @return 序列化後的文本
     */
    @Override
    public String toString() {
        clearPath();
        return toString("/");
    }

    /*
     * 清理path_s。此变量必需清理，否则影响序列化结果。
     */
    protected void clearPath() {
        if (path_s == null) {
            return;
        }
        path_s = null;
        java.util.Iterator keys;
        Object value;
        Object key;

        keys = keys();

        while (keys.hasNext()) {
            key = keys.next();
            value = super.get(key);
            if (value instanceof cc.hanzs.json.JSONObject) {
                ((cc.hanzs.json.JSONObject) value).clearPath();
            } else if (value instanceof cc.hanzs.json.JSONArray) {
                ((cc.hanzs.json.JSONArray) value).clearPath();
            }
        }
    }

    /*
     * @param path 当前所处路径
     */
    protected String toString(final String path) {
        if (path_s != null) {
            return path_s;
        }
        path_s = path;
        java.util.Iterator keys;
        Object value;
        StringBuilder ji_S;
        Object key;

        keys = keys();
        ji_S = new StringBuilder();

        while (keys.hasNext()) {
            ji_S.append(',');

            key = keys.next();
            value = super.get(key);
            if (path.endsWith("/")) {
                value = valueToString(super.get(key), path + key);
            } else {
                value = valueToString(super.get(key), path + "/" + key);
            }
            if (value != null) {
                ji_S.append(quote(key.toString()));
                ji_S.append(':');
                ji_S.append(value);
            }
        }
        if (ji_S.length() > 0) {
            ji_S.replace(0, 1, "{");
            ji_S.append('}');
            int ji_i, ji1_i;
            do {
                ji_i = ji_S.length();
                ji1_i = ji_S.indexOf("{,");
                if (ji1_i > -1) {
                    ji_S.delete(ji1_i + 1, ji1_i + 2);
                }
                ji1_i = ji_S.indexOf(",}");
                if (ji1_i > -1) {
                    ji_S.delete(ji1_i, ji1_i + 1);
                }
            } while (ji_i > ji_S.length());
            return ji_S.toString();
        } else {
            return "{}";
        }
    }
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    /**
     * 移除自身条目及仔项内的条目，彻底清理佔用资源。用于释放
     */
    @Override
    public void clear() {
        java.util.Iterator keys;
        Object value;
        Object key;
        try {
            keys = keys();
            while (keys.hasNext()) {
                key = keys.next();
                value = super.get(key);
                if (value instanceof JSONArray) {
                    ((JSONArray) value).clear();
                } else if (value instanceof JSONObject) {
                    ((JSONObject) value).clear();
                }
            }
            super.clear();
        } catch (Exception e) {
        } finally {
        }
    }

    /**
     * 移除自身的条目，但不移除仔项内的项目，用于清理缓冲
     */
    public void removeall() {
        super.clear();
    }

    /**
     * @return 新的JSONObject对象。
     */
    public static cc.hanzs.json.JSONObject d副本() {
        return (cc.hanzs.json.JSONObject) i_JSON.clone();
    }

    /**
     * @param ci_s 待反序列化的文本
     * @return 新的JSONObject对象。
     */
    public static cc.hanzs.json.JSONObject d副本(final String ci_s) {
        if (ci_s == null) {
            return null;
        }
        cc.hanzs.json.JSONObject jd;
        try {
            jd = (cc.hanzs.json.JSONObject) i_JSON.clone();
            jd.set(JSONTokener.d副本(ci_s));
        } catch (JSONException ex) {
            return null;
        }
        return jd;
    }

    /**
     * @return JSONObject的记录条数。
     */
    public int length() {
        return this.size();
    }
}
